
package ija.model.basis;

import ija.model.types.Color;
import java.util.ArrayList;
import java.util.List;

/**
 * Třída reprezentuje hrací šachovnici.
 * Je realizovaná jako pole objektů Position. Skrze šachovnici se přistupuje ke všem
 * pozicím a figurkám v dané hře.
 * 
 * @author Radek Necas, xnecas18
 */
public class Desk {
    public static final int NORMAL_SIZE = 8;
    
    /** Dvourozměrné pole pozic[řádek][sloupec] */
    protected Position[][] board;
    protected int dimension;
    
    
    ///////////////////////////////////////////////////
    // ---- Pozadovane metody dle API specifikace ---//
    ///////////////////////////////////////////////////
    
    /**
     * Konstruktor vytváří šachovnici daných rozměrů.
     * @param dim rozměry šachovnice (šířka totožná s výškou).
     */
    public Desk(int dim) {
        dimension = dim;
        board = new Position[dim][dim];
        for(int i = 0; i < dim; i++) {
            for(int j = 0; j < dim; j++) {
                board[i][j] = new Position(this, unmapColumn(j), unmapRow(i));
            }
        }
    }
    
    /**
     * Bezparametrický konstruktor vytváří šachovnici standardních rozměrů (8x8).
     */
    public Desk() {
        this(NORMAL_SIZE);
    }
    
    /**
     * Metoda pro získání pozice.
     * @param c identifikátor sloupce
     * @param r identifikátor řádku
     * @return pozice na daném řádku a sloupci
     * 
     * @see ija.model.basis.Position
     */
    public Position getPositionAt(char c, int r) {
        if(isInside(c, r))
            return board[mapRow(r)][mapColumn(c)];
    
        return null;
    }
    
    /**
     * Metoda pro ziskani figurky
     * @param c identifikátor sloupce
     * @param r identifikátor řádku
     * @return figurku na daném řádku a sloupci
     * 
     * @see ija.model.basis.Figure
     */
    public Figure getFigureAt(char c, int r){
        if(isInside(c, r))
            return board[mapRow(r)][mapColumn(c)].getFigure();
        
        return null;
    }
    
    /**
     * Metoda pro ziskani rozměrů šachovnice.
     * @return dimenzi šachovnice. Počet řádků je vždy stejný jako počet sloupců.
     */
    public int getDimension() {
        return dimension;
    }
    
    /**
     * Test zda jsou dané souřadnice uvnitř šachovnice.
     * @param c identifikátor sloupce
     * @param r identifikátor řádku
     * @return true pokud jsou souřadnice uvnitř šachovnice, jinak false.
     */
    public boolean isInside(char c, int r) {
        if(mapRow(r) < 0 || mapColumn(c) < 0)
            return false;
        
        if((mapRow(r) < dimension) && (mapColumn(c) < dimension))
            return true;
        
        return false;
    }
    
    /**
     * Test zda je daná pozice uvnitř šachovnice.
     * Pozice nemusí být v šachovnici, testují se pouze souřadnice pozice.
     * @param p testovaná pozice
     * @return true pokud je pozice v šachovnici, jinak false.
     */
    public boolean isInside(Position p) {
        return(isInside(p.getColumnChar(), p.getRowNumber()));
    }
    
    /**
     * Metoda pro získání všech figurek dané barvy
     * @param c barva figurek, které chceme získat
     * @return list se všemi figurkami dané barvy
     */
    public List<Figure> getAllFigures(Color c) {
        List<Figure> fig = new ArrayList<>();
        Figure f;
        
        for(int row = 1; row < dimension; row++) {
            for(int col = 0; col < dimension; col++){
                f = getFigureAt((char)(col + 'a'), row);
                if(f != null) {
                    if(c == Color.UNKNOWN || c == f.getColor()) {
                        fig.add(f);
                    }
                }
            }
        }
        
        return fig;
    }
    
    /**
     * Metoda pro získání všech figurek
     * @return list se všemi figurkami
     */
    public List<Figure> getAllFigures() {
        return getAllFigures(Color.UNKNOWN);
    }

    /**
     * Vypíše na stdout obsah šachovnice.
     */
    public void print() {
        for(int i = 0; i < dimension; i++) {
            for(int j = 0; j < dimension; j++) {
                board[i][j].print();
                System.out.println();
            }
        }
    }
    
    /**
     * Vypíše na stdout obsah šachovnice, avšak pouze obsazená pole (na kterých je figurka).
     */
    public void printOccupy() {
        for(int i = 0; i < dimension; i++) {
            for(int j = 0; j < dimension; j++) {
                if(board[i][j].getFigure() != null) {
                    board[i][j].print();
                    System.out.println();
                }
            }
        }
    }
    
    
    ////////////////////////////////////////////////////////////////
    // -----------  Soukrome metody ------------------------------//
    ////////////////////////////////////////////////////////////////
    
    
    /** Mapuje pismenne oznaceni sloupce na odpovidajici cislo sloupce v matici board */
    private int mapColumn(char c) {        
        return ((int)c - (int)'a');
    }
    
    /** Mapuje ciselne oznaceni radku na odpovidajici cislo radku v matici board */
    private int mapRow(int r) {
        return(r-1);
    }
    
    /** Mapuje zpetne cislo sloupce matice board na pismenne oznaceni sloupce */
    private char unmapColumn(int c) {
        return((char)((int)'a' + c));
    }
    
    /** Mapuje zpetne cislo radku matice board na pismenne oznaceni radku */
    private int unmapRow(int r) {
        return(r+1);
    }             
}